package com.taochaplan;

import com.vividsolutions.jts.geom.Coordinate;
import com.vividsolutions.jts.geom.GeometryFactory;
import com.vividsolutions.jts.geom.LineString;
import com.vividsolutions.jts.geom.MultiLineString;
import org.geotools.data.FeatureSource;
import org.geotools.data.FeatureWriter;
import org.geotools.data.Transaction;
import org.geotools.data.shapefile.ShapefileDataStore;
import org.geotools.data.shapefile.ShapefileDataStoreFactory;
import org.geotools.data.simple.SimpleFeatureIterator;
import org.geotools.data.simple.SimpleFeatureSource;
import org.geotools.feature.FeatureCollection;
import org.geotools.feature.FeatureIterator;
import org.geotools.feature.simple.SimpleFeatureTypeBuilder;
import org.geotools.referencing.crs.DefaultGeographicCRS;
import org.junit.jupiter.api.Test;
import org.opengis.feature.Property;
import org.opengis.feature.simple.SimpleFeature;
import org.opengis.feature.simple.SimpleFeatureType;
import org.opengis.feature.type.Name;

import java.awt.geom.Point2D;
import java.io.*;
import java.lang.reflect.Field;
import java.nio.charset.Charset;
import java.util.*;

/**
 * @author wbsheng
 * @create 2018-06-02 13:30
 **/
public class Geotools {

    public static List<Pole> readShapePointData(String path) throws Exception {
        List<Pole> resultList = new ArrayList<>();
        //一个数据存储实现，允许从Shapefiles读取和写入
        ShapefileDataStore shpDataStore = null;
        shpDataStore = new ShapefileDataStore(new File(path).toURI().toURL());
        shpDataStore.setCharset(Charset.forName("UTF-8"));
        //获取这个数据存储保存的类型名称数组
        //getTypeNames:获取所有地理图层
        String typeName = shpDataStore.getTypeNames()[0];
        //通过此接口可以引用单个shapefile、数据库表等。与数据存储进行比较和约束
        FeatureSource<SimpleFeatureType, SimpleFeature> featureSource = null;
        featureSource = (FeatureSource<SimpleFeatureType, SimpleFeature>) shpDataStore.getFeatureSource(typeName);
        //一个用于处理FeatureCollection的实用工具类。提供一个获取FeatureCollection实例的机制
        FeatureCollection<SimpleFeatureType, SimpleFeature> result = featureSource.getFeatures();
        FeatureIterator<SimpleFeature> iterator = result.features();
        while (iterator.hasNext()) {
            SimpleFeature feature = iterator.next();
            Collection<Property> p = feature.getProperties();
            Iterator<Property> it = p.iterator();
            //特征里面的属性再迭代,属性里面有字段
            Pole pole = new Pole();
            while (it.hasNext()) {
                Property pro = it.next();
                //如果是点的话,基本上第一个属性字段表示的就是类型
                if (pro.getValue() instanceof com.vividsolutions.jts.geom.Point) {
                    com.vividsolutions.jts.geom.Point point = (com.vividsolutions.jts.geom.Point) pro.getValue();
                    Double[] transform = GPSUtil.tdsptrans(point.getX(), point.getY());
                    Point2D.Double aDouble = GPSUtil.transformToWgs84(transform[0], transform[1]);
                    double[] doubles = CoordinateTransformUtil.wgs84togcj02(aDouble.getX(), aDouble.getY());
                    pole.setX(GPSUtil.retain6(doubles[0]) + "");
                    pole.setY(GPSUtil.retain6(doubles[1]) + "");
                }
                //其余的，正常输出
                else {
                    Name name = pro.getName();
                        Field field = Pole.class.getDeclaredField(name.toString().toLowerCase());
                        if (field != null) {
                            field.setAccessible(true);
                            field.set(pole, pro.getValue().toString());
                        }
                }
            }//end 里层while
            resultList.add(pole);
        }//end 最外层 while
        iterator.close();
        return resultList;
    }


    //4.读shp文件【几何信息+属性信息】
    public List<NetWork> readShapeLineData(String path) throws Exception {
        List<NetWork> resultList = new ArrayList<>();
        ShapefileDataStoreFactory dataStoreFactory = new ShapefileDataStoreFactory();
        File file = new File(path);
        ShapefileDataStore ds = (ShapefileDataStore) dataStoreFactory.createDataStore(file.toURI().toURL());
        //设置编码，防止中文读取乱码
        ds.setCharset(Charset.forName("UTF-8"));
        SimpleFeatureSource featureSource = ds.getFeatureSource();
        FeatureCollection<SimpleFeatureType, SimpleFeature> result = featureSource.getFeatures();
        SimpleFeatureIterator it = (SimpleFeatureIterator) result.features();
        while (it.hasNext()) {
            NetWork netWork = new NetWork();
            SimpleFeature feature = it.next();
            Iterator<Property> ip = feature.getProperties().iterator();
            //再来个while
            while (ip.hasNext()) {
                Property pro = ip.next();
                if (pro.getValue() instanceof MultiLineString) {
                    MultiLineString value = (MultiLineString) pro.getValue();
                    Coordinate[] coordinates = value.getCoordinates();
                    Coordinate[] coors = new Coordinate[coordinates.length];
                    int i = 0;
                    for (Coordinate coor : coordinates) {
                        Double[] transform = GPSUtil.tdsptrans(coor.x, coor.y);
                        Point2D.Double aDouble = GPSUtil.transformToWgs84(transform[0], transform[1]);
                        double[] doubles = CoordinateTransformUtil.wgs84togcj02(aDouble.getX(), aDouble.getY());
                        coor.x = GPSUtil.retain6(doubles[0]);
                        coor.y = GPSUtil.retain6(doubles[1]);
                        coors[i++] = coor;
                    }
                    netWork.setCoordinates(coors);
                } else {
                    Name name = pro.getName();
                    Field field = NetWork.class.getDeclaredField(name.toString().toLowerCase());
                    if (field != null) {
                        field.setAccessible(true);
                        field.set(netWork, pro.getValue().toString());
                    }
                }
            }//end 属性迭代
            resultList.add(netWork);
        }
        it.close();
        return resultList;
    }


    //3.写shp文件，：
    @Test
    public void writeAoMenLine() throws Exception {
        String path = "H:\\logs\\geotools\\aoMenLine.shp";
        //1.创建shape文件对象
        File file = new File(path);
        Map<String, Serializable> params = new HashMap<>();
        //用于捕获参数需求的数据类
        //URLP:url to the .shp file.
        params.put(ShapefileDataStoreFactory.URLP.key, file.toURI().toURL());
        //2.创建一个新的数据存储——对于一个还不存在的文件。
        ShapefileDataStore ds = (ShapefileDataStore) new ShapefileDataStoreFactory().createNewDataStore(params);
        //3.定义图形信息和属性信息
        //SimpleFeatureTypeBuilder 构造简单特性类型的构造器
        SimpleFeatureTypeBuilder tBuilder = new SimpleFeatureTypeBuilder();
        //设置
        //WGS84:一个二维地理坐标参考系统，使用WGS84数据
        tBuilder.setCRS(DefaultGeographicCRS.WGS84);
        tBuilder.setName("shapefile");
        //添加 一条线
        tBuilder.add("the_geom", LineString.class);
        //添加一个id
        tBuilder.add("network_id", String.class);
        //添加名称
        tBuilder.add("route_nos", String.class);
        //添加描述
        //设置此数据存储的特征类型
        ds.createSchema(tBuilder.buildFeatureType());
        //设置编码
        ds.setCharset(Charset.forName("UTF-8"));
        //设置writer
        FeatureWriter<SimpleFeatureType, SimpleFeature> writer = ds.getFeatureWriter(
                ds.getTypeNames()[0], Transaction.AUTO_COMMIT);
        //Interface SimpleFeature：一个由固定列表值以已知顺序组成的SimpleFeatureType实例。
        //写一个点
        GeometryFactory geometryFactory = new GeometryFactory();
        List<NetWork> netWorks = readShapeLineData("G:\\BANYUN\\ExportShapeFile20180124\\ROUTE_NETWORK.shp");
        for (NetWork netWork : netWorks) {
            SimpleFeature feature = writer.next();
            feature.setAttribute("the_geom", geometryFactory.createLineString(netWork.getCoordinates()));
            feature.setAttribute("network_id", netWork.getNetwork_id());
            feature.setAttribute("route_nos", netWork.getRoute_nos());
        }
        //写入
        writer.write();
        //关闭
        writer.close();
        //释放资源
        ds.dispose();
    }


    @Test
    public void read() throws Exception {
        String path = "H:\\logs\\geotools\\gaoDeLine.shp";
        //1.创建shape文件对象
        File file = new File(path);
        Map<String, Serializable> params = new HashMap<>();
        //用于捕获参数需求的数据类
        //URLP:url to the .shp file.
        params.put(ShapefileDataStoreFactory.URLP.key, file.toURI().toURL());
        //2.创建一个新的数据存储——对于一个还不存在的文件。
        ShapefileDataStore ds = (ShapefileDataStore) new ShapefileDataStoreFactory().createNewDataStore(params);
        //3.定义图形信息和属性信息
        //SimpleFeatureTypeBuilder 构造简单特性类型的构造器
        SimpleFeatureTypeBuilder tBuilder = new SimpleFeatureTypeBuilder();
        //设置
        //WGS84:一个二维地理坐标参考系统，使用WGS84数据
        tBuilder.setCRS(DefaultGeographicCRS.WGS84);
        tBuilder.setName("shapefile");
        //添加 一条线
        tBuilder.add("the_geom", LineString.class);
        //添加一个id
        tBuilder.add("link_id", String.class);
        //添加名称
        tBuilder.add("dir", String.class);
        //添加描述
        //设置此数据存储的特征类型
        ds.createSchema(tBuilder.buildFeatureType());
        //设置编码
        ds.setCharset(Charset.forName("UTF-8"));
        //设置writer
        FeatureWriter<SimpleFeatureType, SimpleFeature> writer = ds.getFeatureWriter(
                ds.getTypeNames()[0], Transaction.AUTO_COMMIT);
        //Interface SimpleFeature：一个由固定列表值以已知顺序组成的SimpleFeatureType实例。
        //写一个点
        GeometryFactory geometryFactory = new GeometryFactory();
        List<GaoDeLine> gaoDeLines = readGaoDeLine();
    }

    @Test
    public void writeAoMenPoint() throws Exception {
        String path = "H:\\logs\\geotools\\aoMenPoint.shp";
        //1.创建shape文件对象
        File file = new File(path);
        Map<String, Serializable> params = new HashMap<>();
        //用于捕获参数需求的数据类
        //URLP:url to the .shp file.
        params.put(ShapefileDataStoreFactory.URLP.key, file.toURI().toURL());
        //2.创建一个新的数据存储——对于一个还不存在的文件。
        ShapefileDataStore ds = (ShapefileDataStore) new ShapefileDataStoreFactory().createNewDataStore(params);
        //3.定义图形信息和属性信息
        //SimpleFeatureTypeBuilder 构造简单特性类型的构造器
        SimpleFeatureTypeBuilder tBuilder = new SimpleFeatureTypeBuilder();
        //设置
        //WGS84:一个二维地理坐标参考系统，使用WGS84数据
        tBuilder.setCRS(DefaultGeographicCRS.WGS84);
        tBuilder.setName("shapefile");
        //添加 一个点
        tBuilder.add("the_geom", com.vividsolutions.jts.geom.Point.class);
        tBuilder.add("sid", String.class);
        tBuilder.add("pole_id", String.class);
        tBuilder.add("p_name", String.class);
        tBuilder.add("alias", String.class);
        tBuilder.add("name", String.class);
        tBuilder.add("route_nos", String.class);
        //设置编码
        ds.setCharset(Charset.forName("UTF-8"));
        ds.createSchema(tBuilder.buildFeatureType());

        //设置writer
        FeatureWriter<SimpleFeatureType, SimpleFeature> writer = ds.getFeatureWriter(
                ds.getTypeNames()[0], Transaction.AUTO_COMMIT);
        //Interface SimpleFeature：一个由固定列表值以已知顺序组成的SimpleFeatureType实例。
        List<Pole> poles = readShapePointData("G:\\BANYUN\\ExportShapeFile20180124\\BUS_POLE.shp");
        for (Pole pp : poles) {
            //写一个点
            SimpleFeature feature = writer.next();
            Coordinate coordinate = new Coordinate(Double.parseDouble(pp.getX()), Double.parseDouble(pp.getY()));
            com.vividsolutions.jts.geom.Point point = new GeometryFactory().createPoint(coordinate);
            feature.setAttribute("the_geom", point);
            feature.setAttribute("sid", pp.getSid());
            feature.setAttribute("pole_id", pp.getPole_id());
            feature.setAttribute("p_name", pp.getP_name());
            feature.setAttribute("alias", pp.getAlias());
            feature.setAttribute("name", pp.getName());
            feature.setAttribute("route_nos", pp.getRoute_nos());
        }
        //写入
        writer.write();
        //关闭
        writer.close();
        //释放资源
        ds.dispose();
    }


    public static List<GaoDePoint> readGaoDePoint() {
        String pointPath = "G:\\BANYUN\\aomen\\inter_info.csv";
        List<GaoDePoint> resultList = new ArrayList<>();
        try {
            //换成你的文件名
            BufferedReader reader = new BufferedReader(new InputStreamReader(new FileInputStream(pointPath), "UTF-8"));
            reader.readLine();//第一行信息，为标题信息，不用,如果需要，注释掉
            String line = null;
            String inter_id = "";
            String inter_name = "";
            while ((line = reader.readLine()) != null) {
                GaoDePoint point = new GaoDePoint();
                //CSV格式文件为逗号分隔符文件，这里根据逗号切分
                String item[] = line.split(",");
                //这就是你要的数据了
                inter_id = item[0];
                inter_name = item[1];
                String lat = item[2];
                String lng = item[3];
                point.setInterId(inter_id);
                point.setInterName(inter_name);
                point.setLat(Double.parseDouble(lat));
                point.setLng(Double.parseDouble(lng));
                resultList.add(point);
            }
        } catch (Exception e) {
            e.printStackTrace();
        }
        return resultList;
    }

    @Test
    public void writeGaoDePoint() throws Exception {
        String path = "H:\\logs\\geotools\\gaoDePoint.shp";
        //1.创建shape文件对象
        File file = new File(path);

        Map<String, Serializable> params = new HashMap<>();

        //用于捕获参数需求的数据类
        //URLP:url to the .shp file.
        params.put(ShapefileDataStoreFactory.URLP.key, file.toURI().toURL());

        //2.创建一个新的数据存储——对于一个还不存在的文件。
        ShapefileDataStore ds = (ShapefileDataStore) new ShapefileDataStoreFactory().createNewDataStore(params);

        //3.定义图形信息和属性信息
        //SimpleFeatureTypeBuilder 构造简单特性类型的构造器
        SimpleFeatureTypeBuilder tBuilder = new SimpleFeatureTypeBuilder();

        //设置
        //WGS84:一个二维地理坐标参考系统，使用WGS84数据
        tBuilder.setCRS(DefaultGeographicCRS.WGS84);
        tBuilder.setName("shapefile");
        //添加 一个点
        tBuilder.add("the_geom",  com.vividsolutions.jts.geom.Point.class);
        tBuilder.add("inter_id", String.class);
        tBuilder.add("inter_name", String.class);

        //设置此数据存储的特征类型
        SimpleFeatureType simpleFeatureType = tBuilder.buildFeatureType();
        ds.createSchema(simpleFeatureType);

        //设置编码
        ds.setCharset(Charset.forName("UTF-8"));
        //设置writer
        FeatureWriter<SimpleFeatureType, SimpleFeature> writer = ds.getFeatureWriter(
                ds.getTypeNames()[0], Transaction.AUTO_COMMIT);

        //Interface SimpleFeature：一个由固定列表值以已知顺序组成的SimpleFeatureType实例。
        List<GaoDePoint> gaoDePoints = readGaoDePoint();
        for (GaoDePoint gaode : gaoDePoints) {
            //写一个点
            SimpleFeature feature = writer.next();
            Coordinate coordinate = new Coordinate(gaode.getLat(), gaode.getLng());
            com.vividsolutions.jts.geom.Point point = new GeometryFactory().createPoint(coordinate);
            feature.setAttribute("the_geom", point);
            feature.setAttribute("inter_id", gaode.getInterId());
            feature.setAttribute("inter_name", gaode.getInterName());
        }
        //写入
        writer.write();
        //关闭
        writer.close();
        //释放资源
        ds.dispose();
    }


    public static List<GaoDeLine> readGaoDeLine() throws Exception {
        List<GaoDeLine> resultList = new ArrayList<>();
        String link_id = "";
        String loc_arr = "";
        String dir = "";
        String pointPath = "G:\\BANYUN\\aomen\\link_info.csv";
        //换成你的文件名
        BufferedReader reader = new BufferedReader(new FileReader(pointPath));
        reader.readLine();//第一行信息，为标题信息，不用,如果需要，注释掉
        String line = null;
        while ((line = reader.readLine()) != null) {
            GaoDeLine gaoDeLine = new GaoDeLine();
            //CSV格式文件为逗号分隔符文件，这里根据逗号切分
            String item[] = line.split(",\"");
            //这就是你要的数据了
            gaoDeLine.setLinkId(item[0]);
            loc_arr = item[2];
            dir = loc_arr.substring(loc_arr.length() - 1, loc_arr.length());
            gaoDeLine.setDir(dir);
            loc_arr = loc_arr.substring(0, loc_arr.length() - 3);
            String[] pointStr = loc_arr.split(":");
            List<Point> listPoint = new ArrayList<>();
            for (String str : pointStr) {
                String[] op = str.split(",");
                String x = op[0];
                String y = op[1];
                Point pp = new Point();
                pp.setX(Double.parseDouble(x));
                pp.setY(Double.parseDouble(y));
                listPoint.add(pp);
            }
            gaoDeLine.setPointList(listPoint);
            resultList.add(gaoDeLine);
        }
        return resultList;
    }

    @Test
    public void writeGaoDeLine() throws Exception {
        String path = "H:\\logs\\geotools\\gaoDeLine.shp";
        //1.创建shape文件对象
        File file = new File(path);
        Map<String, Serializable> params = new HashMap<>();
        //用于捕获参数需求的数据类
        //URLP:url to the .shp file.
        params.put(ShapefileDataStoreFactory.URLP.key, file.toURI().toURL());
        //2.创建一个新的数据存储——对于一个还不存在的文件。
        ShapefileDataStore ds = (ShapefileDataStore) new ShapefileDataStoreFactory().createNewDataStore(params);
        //3.定义图形信息和属性信息
        //SimpleFeatureTypeBuilder 构造简单特性类型的构造器
        SimpleFeatureTypeBuilder tBuilder = new SimpleFeatureTypeBuilder();
        //设置
        //WGS84:一个二维地理坐标参考系统，使用WGS84数据
        tBuilder.setCRS(DefaultGeographicCRS.WGS84);
        tBuilder.setName("shapefile");
        //添加 一条线
        tBuilder.add("the_geom", LineString.class);
        //添加一个id
        tBuilder.add("link_id", String.class);
        //添加名称
        tBuilder.add("dir", String.class);
        //添加描述
        //设置此数据存储的特征类型
        ds.createSchema(tBuilder.buildFeatureType());
        //设置编码
        ds.setCharset(Charset.forName("UTF-8"));
        //设置writer
        FeatureWriter<SimpleFeatureType, SimpleFeature> writer = ds.getFeatureWriter(
                ds.getTypeNames()[0], Transaction.AUTO_COMMIT);
        //Interface SimpleFeature：一个由固定列表值以已知顺序组成的SimpleFeatureType实例。
        //写一个点
        GeometryFactory geometryFactory = new GeometryFactory();
        List<GaoDeLine> gaoDeLines = readGaoDeLine();
        for (GaoDeLine gaoDeLine : gaoDeLines) {
            SimpleFeature feature = writer.next();
            Coordinate[] coordinates = new Coordinate[gaoDeLine.getPointList().size()];
            int i = 0;
            for (Point pp : gaoDeLine.getPointList()) {
                Coordinate coordinate = new Coordinate();
                coordinate.y = pp.getY();
                coordinate.x = pp.getX();
                coordinates[i++] = coordinate;
            }
            feature.setAttribute("the_geom", geometryFactory.createLineString(coordinates));
            feature.setAttribute("link_id", gaoDeLine.getLinkId());
            feature.setAttribute("dir", gaoDeLine.getDir());
        }
        //写入
        writer.write();
        //关闭
        writer.close();
        //释放资源
        ds.dispose();
    }


}
